/*
Condition-conclusion rule system
with backward chaining


Rules are represented by facts of the form rule(Condition, Conclusion).
- Condition is an atomic proposition, a conjunction of conditions,
  or a negataion of a condition
- A Conclusion is a literal
- Negated literals are represented by the untrue predicate

Facts are represented by facts of the form fact(Fact).


2001/03/23
Luis Botelho

Asking system was changed to avoid the assertion of not-ground terms
2010/10/15
Luis Mota
*/



:- dynamic fact/1.


:- op(10, xfy, then).
:- op(100, fx, if).

:- op(1000, xfy, and).
:- op(1100, xfy, or).


rule(A, B):- if A then B.

solve(P):- fact(P).

solve((A, B)):- !, solve(A), solve(B).
solve((A and B)):- !, solve(A), solve(B).

solve((A; B)):- !, (solve(A); solve(B)).
solve((A or B)):- !, (solve(A); solve(B)).

solve(not(P)):-
 !,
 \+ solve(P).

solve(P):- rule(Q, P), solve(Q).

solve(P):- system(P), !, call(P).


solve(P):-
	askable(P),
	\+ known(P),
	possible_answers(P,PAnswers),
	ask(P, Answer,PAnswers),
	process_answer(P, Answer).

system(P):-
	predicate_property(P, built_in).

known(P):- fact(P);fact(not(P)), !.


ask(P, Answer,PAnswers):-
	prompt(Old, ''),
	repeat,
	write(P), write_answers(PAnswers),
	read(Answer),
	(Answer\=fact,member(Answer,PAnswers);
	 unify_with_occurs_check(P,Answer),ground(Answer)),!,
	prompt(_, Old).

possible_answers(P,[yes,no]):-ground(P).
possible_answers(P,[no,fact]):- \+(ground(P)).

write_answers(PAnswers):-write('('),write_answers_aux(PAnswers),write(')?').
write_answers_aux([A]):-write(A),!.
write_answers_aux([A|R]):-write(A),write('/'),write_answers_aux(R).

process_answer(P, yes):- !, assert(fact(P)).
process_answer(P, P):- !, assert(fact(P)).
process_answer(P, no):- !, assert(fact(not(P))), fail.
process_answer(P, not(P)):- !, assert(fact(not(P))), fail.


% KB
if   (vo(X), largura(X, muito_largo), comprimento(X, muito_comprido))
then camioneta(X).

if camioneta(X) then velocidade_maxima(X, media).

fact(vo(vo01)).
fact(vo(vo02)).
fact(vo(vo03)).
fact(vo(vo04)).


askable(largura(_,_)).
askable(comprimento(_,_)).

/*
fact(largura(v01, muito_largo)).
fact(comprimento(v01, muito_comprido)).
*/


fact(homem(luis)).
fact(homem(bernardo)).
fact(mulher(ana)).
askable(filho(_,_)).

/*fact(filho(ana, luis)).
fact(filho(luis,bernardo)).
*/

if (homem(X) and filho(_, X)) then pai(X).

if (homem(X) and filho(Y, X) and filho(_,Y)) then avo(X).

